package com.seecoder.BlueWhale.serviceImpl;

import com.seecoder.BlueWhale.annotation.RoleAccessCheck;
import com.seecoder.BlueWhale.configure.AlipayTools;
import com.seecoder.BlueWhale.enums.RoleEnum;
import com.seecoder.BlueWhale.enums.OrderStatusEnum;
import com.seecoder.BlueWhale.exception.BlueWhaleException;
import com.seecoder.BlueWhale.po.*;
import com.seecoder.BlueWhale.repository.*;
import com.seecoder.BlueWhale.service.CouponGroupService;
import com.seecoder.BlueWhale.service.OrderService;
import com.seecoder.BlueWhale.serviceImpl.payStrategy.AlipayPay;
import com.seecoder.BlueWhale.serviceImpl.payStrategy.PayStrategy;
import com.seecoder.BlueWhale.serviceImpl.payStrategy.TestSuccessPay;
import com.seecoder.BlueWhale.util.OssUtil;
import com.seecoder.BlueWhale.util.SecurityUtil;
import com.seecoder.BlueWhale.vo.*;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.impl.xb.ltgfmt.TestsDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.io.*;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    AlipayTools alipayTools;

    @Autowired
    OrderRepository orderRepository;

    @Autowired
    StoreRepository storeRepository;

    @Autowired
    SecurityUtil securityUtil;

    @Autowired
    OssUtil ossUtil;

    @Autowired
    CommodityServiceImpl commodityService;

    @Autowired
    CommodityRepository commodityRepository;

    @Autowired
    CommentRepository commentRepository;

    @Autowired
    CouponRepository couponRepository;

    @Autowired
    CouponGroupService couponGroupService;

    @Autowired
    CouponGroupRepository couponGroupRepository;

    @Autowired
    AlipayPay alipayPay;

    @Autowired
    TestSuccessPay testSuccessPay;

    private final PayStrategy payStrategy;

    public OrderServiceImpl(@Qualifier("alipayPay") AlipayPay alipayPay,
                            @Qualifier("testSuccessPay") TestSuccessPay testSuccessPay) {
        this.payStrategy = testSuccessPay;
    }


    @Override
    @RoleAccessCheck(role = RoleEnum.CUSTOMER)
    public OrderVO create(OrderVO orderVO) {
        //获取当前创建订单的用户id
        User user = securityUtil.getCurrentUser();

        //获取当前创建订单的商品信息
        Commodity orderCommodity = commodityService.info(orderVO.getCommodityID()).toPO();

        if (orderCommodity.getExpectQuantity() < orderVO.getQuantity()) {
            throw BlueWhaleException.CommodityInsufficient();//订单商品数量不能超过预期库存
        }

        //我这里的想法是因为按照道理不同商店应该可以有相同名字的商品（前面没有考虑等会debug）
        //前端还是只传id  否则前端要再调商品那个接口获取商品信息  干脆后端调 甚至可以顺便判断库存
        //idea 提示我把这个过程提取成getNewOrder方法了(
        Order newOrder = getNewOrder(orderVO, orderCommodity, user);
        orderRepository.save(newOrder);

        orderCommodity.setExpectQuantity(orderCommodity.getExpectQuantity() - newOrder.getQuantity());
        commodityRepository.save(orderCommodity);

        return newOrder.toVO();
    }

    @Override
    @RoleAccessCheck(role = RoleEnum.CUSTOMER)
    public Boolean pay(PayParams params, HttpServletResponse httpServletResponse) {
        return payStrategy.pay(params, httpServletResponse);
    }

    @Override
    @RoleAccessCheck(role = RoleEnum.STAFF)
    public Boolean dispatch(Integer orderID) {
        Order order = orderRepository.findById(orderID.intValue());

        if (order == null) {
            throw BlueWhaleException.orderNotFound();
        } else if (!Objects.equals(order.getStoreID(), securityUtil.getCurrentUser().getStoreId())) {
            throw BlueWhaleException.storeAccessInvalid();
        } else if (order.getStatus() != OrderStatusEnum.UNSEND) {   //订单为空显示未查询到
            throw BlueWhaleException.orderStatusWrong();     //商店管理员只能发本商店的订单
        }                                                    //订单状态不为UNSEND将抛出异常

        order.setStatus(OrderStatusEnum.UNGET);
        orderRepository.save(order);
        //更新商品库存
        Commodity updateCommodity = commodityService.info(order.getCommodityID()).toPO();
        commodityService.changeQuantity(updateCommodity.getId(), updateCommodity.getQuantity() - order.getQuantity());

        return true;
    }

    @Override
    @RoleAccessCheck(role = RoleEnum.CUSTOMER)
    public Boolean receive(Integer orderID) {
        Order order = orderRepository.findById(orderID.intValue());

        if (order == null) {
            throw BlueWhaleException.orderNotFound();
        } else if (order.getStatus() != OrderStatusEnum.UNGET) {
            throw BlueWhaleException.orderStatusWrong();
        }

        order.setStatus(OrderStatusEnum.UNCOMMENT);
        orderRepository.save(order);
        return true;
    }

    @Override
    public PageVO<OrderVO> info(int page, int pageSize) {
        List<OrderVO> orderVOList = null;
        switch (securityUtil.getCurrentUser().getRole()) {
            case CUSTOMER:
                orderVOList = orderRepository.findAllByOwnerID(securityUtil.getCurrentUser().getId()).stream().map(Order::toVO).collect(Collectors.toList());
                break;
            case STAFF:
                orderVOList = orderRepository.findAllByStoreID(securityUtil.getCurrentUser().getStoreId()).stream().map(Order::toVO).collect(Collectors.toList());
                break;
            default:
                orderVOList = orderRepository.findAll().stream().map(Order::toVO).collect(Collectors.toList());
                break;
        }
        for (OrderVO orderVO : orderVOList){
            orderVO = warp(orderVO);
        }
        return new PageVO<>(orderVOList, page, pageSize);
    }

    @Override
    @RoleAccessCheck(role = RoleEnum.CUSTOMER)
    public CommentVO comment(CommentVO commentVO) {
        Order order = orderRepository.findById(commentVO.getOrderID().intValue());
        User user = securityUtil.getCurrentUser();


        if (order == null) {
            throw BlueWhaleException.orderNotFound();
        } else if (order.getStatus() != OrderStatusEnum.UNCOMMENT) {
            throw BlueWhaleException.orderStatusWrong();
        }

        Comment newcomment = commentVO.toPO();
        newcomment.setUserID(user.getId());
        newcomment.setUserName(user.getName());
        newcomment.setCreateTime(new Date());
        newcomment.setCommodityID(order.getCommodityID());
        commentRepository.save(newcomment);

        order.setStatus(OrderStatusEnum.DONE);
        orderRepository.save(order);


        commodityService.updateRating(order.getCommodityID());


        return newcomment.toVO();
    }

    @Override
    public OrderVO infoSingle(int id) {
        Order order = orderRepository.findById(id);

        if (order == null) {
            throw BlueWhaleException.orderNotFound();
        } else {
            return warp(order.toVO());
        }
    }

    @Override
    public CommentVO getComment(int id) {
        Order order = orderRepository.findById(id);
        if (order.getStatus() != OrderStatusEnum.DONE) {
            throw BlueWhaleException.orderStatusWrong();
        }
        return commentRepository.findByOrderID(id).toVO();
    }

    private static Order getNewOrder(OrderVO orderVO, Commodity orderCommodity, User user) {
        Order newOrder = new Order();

        newOrder.setCreateTime(new Date());
        newOrder.setStatus(OrderStatusEnum.UNPAID);
        //订单的商店id、价格、商品名、图片通过商品的所属商店id来获取
        newOrder.setCommodityID(orderCommodity.getId());
        newOrder.setStoreID(orderCommodity.getStoreId());
        //数量、送货方式接受前端数据
        newOrder.setQuantity(orderVO.getQuantity());
        newOrder.setDeliveryMethod(orderVO.getDeliveryMethod());
        //创建者id通过当前user信息获取
        newOrder.setOwnerID(user.getId());
        return newOrder;
    }

    @Override
    public String getExcel() {
        User user = securityUtil.getCurrentUser();
        try (Workbook workbook = new XSSFWorkbook()) {
            if (user.getRole() == RoleEnum.STAFF) {
                genExcel(user.getStoreId(), workbook);
            } else if (user.getRole() == RoleEnum.CEO) {
                for (Store store : storeRepository.findAll()) {
                    genExcel(store.getId(), workbook);
                }
            } else {
                throw BlueWhaleException.invalidExcelRequest();
            }
            File tempFile = File.createTempFile("order", ".xlsx");
            String path;
            try (OutputStream outputStream = new FileOutputStream(tempFile)) {
                workbook.write(outputStream);
            }
//            try (InputStream inputStream = new FileInputStream(tempFile)) {
//                path = ossUtil.upload(tempFile.getName(), inputStream);
//            }
//            assert (tempFile.delete());
            return tempFile.getPath();
        } catch (IOException ioException) {
            System.err.println("Error when create workbook!");
            ioException.printStackTrace();
        }
        return null;
    }

    /**
     * 生成excel表格
     *
     * @param storeID  商店id
     * @param workbook 工作簿
     */
    private void genExcel(int storeID, Workbook workbook) {
        String[] headers = {"订单id", "创建时间", "交易人", "商品", "送货方式", "订单状态"};
        List<Order> orders = orderRepository.findAllByStoreID(storeID);
        Sheet sheet = workbook.createSheet("store" + storeID);
        int nrRows = 0;
        Row header = sheet.createRow(nrRows++);
        for (int i = 0; i < headers.length; i += 1) {
            header.createCell(i).setCellValue(headers[i]);
        }
        for (Order order : orders) {
            Commodity commodity = commodityService.info(order.getCommodityID()).toPO();
            Row dataRow = sheet.createRow(nrRows++);
            dataRow.createCell(0).setCellValue(order.getId());
            dataRow.createCell(1).setCellValue(order.getCreateTime());
            dataRow.createCell(2).setCellValue(order.getOwnerID());
            dataRow.createCell(3).setCellValue(commodity.getName());
            dataRow.createCell(4).setCellValue(order.getDeliveryMethod().toString());
            dataRow.createCell(5).setCellValue(order.getStatus().toString());
        }
    }

    /**
     *
     * 包装订单VO
     * @param orderVO 订单VO
     * @return 包装后的订单VO
     */
    public OrderVO warp(OrderVO orderVO){
        Commodity orderCommodity = commodityService.info(orderVO.getCommodityID()).toPO();
        orderVO.setCommodityName(orderCommodity.getName());
        orderVO.setPrice(orderCommodity.getPrice());
        return orderVO;
    }
}
